#include "MainWindow.h"

#include "QRegExp"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent) {
    mainWidget = new QWidget();
    mainWidget->setFixedSize(QSize(WINDOW_WIDTH, WINDOW_HEIGHT));
    glConnectFour = new GLConnectFour();
    sideWidget = new SideWidget();
    chatWidget = sideWidget->getChatWidget();
    gameManager = new GameManager(this);

    QHBoxLayout * mainLayout = new QHBoxLayout;
    mainLayout->addWidget(glConnectFour);
    mainLayout->addWidget(sideWidget);
    mainLayout->setMargin(0);
    mainWidget->setLayout(mainLayout);
    setCentralWidget(mainWidget);
    setWindowTitle(tr("Connect Four"));

    createActions();
    createMenus();
    connectSignalSlots();

    newGame();

    setFocusPolicy(Qt::StrongFocus);
    setFocus(Qt::ActiveWindowFocusReason);

    FIX_WINDOW_SIZE;
}

void MainWindow::mousePressEvent(QMouseEvent * event) {
    if (event->x() < 525) {
        gameManager->requestMove(event->x() / LENGTH_CELL);
    }
}

void MainWindow::keyPressEvent(QKeyEvent * event) {
    switch (event->key()) {
    case Qt::Key_1:
        gameManager->requestMove(0);
        break;
    case Qt::Key_2:
        gameManager->requestMove(1);
        break;
    case Qt::Key_3:
        gameManager->requestMove(2);
        break;
    case Qt::Key_4:
        gameManager->requestMove(3);
        break;
    case Qt::Key_5:
        gameManager->requestMove(4);
        break;
    case Qt::Key_6:
        gameManager->requestMove(5);
        break;
    case Qt::Key_7:
        gameManager->requestMove(6);
        break;
    case Qt::Key_Escape:
        emit quit();
        break;
    default:
        QWidget::keyPressEvent(event);
        break;
    }
}

void MainWindow::connectSignalSlots() {
    connectGameSignalSlots();
    connect(sideWidget, SIGNAL(newConnection(Network::ConnectionStatus, QTcpSocket*)), this, SLOT(newGameManager(Network::ConnectionStatus, QTcpSocket*)));
}

void MainWindow::connectGameSignalSlots() {
    connect(gameManager, SIGNAL(newGameStarted()), glConnectFour, SLOT(resetGL()));
    connect(gameManager, SIGNAL(playerChanged(ConnectFour::Piece)), sideWidget, SLOT(changeTurn(ConnectFour::Piece)));
    connect(gameManager, SIGNAL(needsAnimation(Animation::AnimationMode, int, ConnectFour::Piece)), glConnectFour, SLOT(startAnimation(Animation::AnimationMode, int, ConnectFour::Piece)));
    connect(glConnectFour, SIGNAL(animationFinished(Animation::AnimationMode)), gameManager, SLOT(finishAnimation(Animation::AnimationMode)));
    connect(gameManager, SIGNAL(columnNeedsUpdate(BoardColumn*,int)), glConnectFour, SLOT(compileColumnList(BoardColumn*,int)));
    connect(gameManager, SIGNAL(winNeedsUpdate(ConnectFour::Win*, ConnectFour::Direction, ConnectFour::Piece)), glConnectFour, SLOT(compileWinList(ConnectFour::Win*, ConnectFour::Direction, ConnectFour::Piece)));
    connect(gameManager, SIGNAL(winPiece(ConnectFour::Piece)), sideWidget, SLOT(incrementScore(ConnectFour::Piece)));
}

void MainWindow::newGame() {
    gameManager->newGame();
}

void MainWindow::requestNewGame() {
    gameManager->requestNewGame();
}

void MainWindow::undo() {
    gameManager->requestUndo();
}

void MainWindow::newGameManager(Network::ConnectionStatus status, QTcpSocket * socket) {
    delete gameManager;
    switch (status) {
    case Network::DISCONNECTED:
        gameManager = new GameManager(this);
        break;
    case Network::HOSTING_CONNECTED:
        gameManager = new TCPGameManager(this, socket, ConnectFour::BLACK, chatWidget);
        break;
    case Network::CLIENT_CONNECTED:
        gameManager = new TCPGameManager(this, socket, ConnectFour::RED, chatWidget);
        break;
    default:
        break;
    }
    connectGameSignalSlots();
    newGame();
}

void MainWindow::createActions() {
    newGameAction = new QAction(tr("&New Game"), this);
    newGameAction->setShortcuts(QKeySequence::New);
    newGameAction->setStatusTip(tr("Start a new game"));
    connect(newGameAction, SIGNAL(triggered()), this, SLOT(requestNewGame()));

    undoAction = new QAction(tr("&Undo"), this);
    undoAction->setShortcuts(QKeySequence::Undo);
    undoAction->setStatusTip(tr("Undo the previous move"));
    connect(undoAction, SIGNAL(triggered()), this, SLOT(undo()));
}

void MainWindow::createMenus() {
    gameMenu = menuBar()->addMenu(tr("&Game"));
    gameMenu->addAction(newGameAction);
    gameMenu->addAction(undoAction);
}
